package com.ruicar.afs.cloud.risk.tortoise.processor.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.BusinessTypeEnum;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.CarNatureEnum;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.CustRoleEnum;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.WhetherEnum;
import com.ruicar.afs.cloud.risk.api.dto.business.*;
import com.ruicar.afs.cloud.risk.api.dto.tortoise.TortoiseQueryBean;
import com.ruicar.afs.cloud.risk.api.dto.tortoise.request.TortoiseApplyData;
import com.ruicar.afs.cloud.risk.api.dto.tortoise.request.TortoiseFraudPushData;
import com.ruicar.afs.cloud.risk.api.dto.tortoise.request.TortoisePrevApproveData;
import com.ruicar.afs.cloud.risk.tortoise.components.GwtInnerServerRequest;
import com.ruicar.afs.cloud.risk.tortoise.components.GwtTortoiseStrRedis;
import com.ruicar.afs.cloud.risk.tortoise.consts.GwtTortoiseConst;
import com.ruicar.afs.cloud.risk.tortoise.dto.notice.GwtTortoiseReq;
import com.ruicar.afs.cloud.risk.tortoise.dto.response.GwtTortoiseResponse;
import com.ruicar.afs.cloud.risk.tortoise.dto.response.apply.*;
import com.ruicar.afs.cloud.risk.api.enums.tortoise.GwtTortoiseScene;
import com.ruicar.afs.cloud.risk.tortoise.entity.CreditTortoiseRecord;
import com.ruicar.afs.cloud.risk.tortoise.enums.GwtTortoiseNoticeClientUri;
import com.ruicar.afs.cloud.risk.tortoise.processor.GwtTortoiseQueryAndNoticeProcessor;
import com.ruicar.afs.cloud.risk.tortoise.service.AfsCreditTortoiseRecordService;
import com.ruicar.afs.cloud.risk.tortoise.util.AfsEnumEmptyUtil;
import com.ruicar.afs.cloud.risk.tortoise.util.RefDataUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;

/**
 * @Description
 * @Author Peng Jinbo
 * @Date 2020/07/30 17:36
 */
@Component
@AllArgsConstructor
@Slf4j
public class GwtTortoiseApplyProcessorImpl implements GwtTortoiseQueryAndNoticeProcessor {

    /**
     * Gwt str redis
     */
    private final GwtTortoiseStrRedis gwtStrRedis;
    /**
     * Afs credit tortoise record service
     */
    private AfsCreditTortoiseRecordService afsCreditTortoiseRecordService;

    /**
     * Gwt inner server request
     */
    private GwtInnerServerRequest gwtInnerServerRequest;


    /**
     * Author Peng Jinbo
     * Set default expire when not exists data *
     * 玄武调用完毕后，数据会被清理
     * s玄武系统仍然会有调用的情况，用于排查异常....等b等情况
     *
     * @param mainId main id
     * @param scene  scene
     */
    public void setDefaultExpireWhenNotExistsData(String mainId,GwtTortoiseScene scene){
        if(gwtStrRedis.notHas(mainId,scene)){
            Optional<CreditTortoiseRecord> optional = afsCreditTortoiseRecordService.list(
                    Wrappers.<CreditTortoiseRecord>lambdaQuery()
                        .eq(CreditTortoiseRecord::getMainId,mainId)
                        .eq(CreditTortoiseRecord::getSceneCode,scene)
            ).stream().findFirst();
            if(optional.isPresent()){
                log.info("临时业务数据获取：MainId：{},Scene：{}",mainId,scene);
                CreditTortoiseRecord record = optional.get();
                Map<String,String> reqBody = new HashMap<>();
                reqBody.put("mainId",mainId);
                reqBody.put("scene", AfsEnumEmptyUtil.key(scene));
                IResponse queryResp;
                TypeReference typeReference;
                if(GwtTortoiseScene.PREV_APPROVE == scene){
                    typeReference = new TypeReference<TortoisePrevApproveData>(){};
                }else if(GwtTortoiseScene.FRAUD_PUSH == scene){
                    typeReference = new TypeReference<TortoiseFraudPushData>(){};
                }else{
                    typeReference = new TypeReference<TortoiseApplyData>(){};
                }
                queryResp = gwtInnerServerRequest.get(record.getClientServerName(), GwtTortoiseConst.DATA_QUERY_CLIENT_URI, reqBody, typeReference);
                if(CommonConstants.SUCCESS.equals(queryResp.getCode()) && Objects.nonNull(queryResp.getData())){
                    gwtStrRedis.defaultExpireSet((TortoiseQueryBean) queryResp.getData());
                }else{
                    log.warn("业务端数据获取失败:" + queryResp);
                }
            }
        }
    }


    /**
     * Author Peng Jinbo
     * Belong scene set
     *
     * @return the set
     */
    @Override
    public Set<GwtTortoiseScene> belongScene() {
        return new HashSet<GwtTortoiseScene>() {{
            add(GwtTortoiseScene.NORMAL_APPLY);
        }};
    }

    /**
     * Author Peng Jinbo
     * Query gwt tortoise response
     *
     * @param notice notice
     * @return the gwt tortoise response
     */
    @Override
    public GwtTortoiseResponse query(GwtTortoiseReq notice) {
        setDefaultExpireWhenNotExistsData(notice.getCaMainId(),notice.getSceneCode());
        TortoiseApplyData tortoiseApplyData = gwtStrRedis.assertGet(notice, TortoiseApplyData.class);
        ApplyMainInfo mainInfo = tortoiseApplyData.getApplyMainInfo();
        ApplyCostInfo costInfo = tortoiseApplyData.getApplyCostInfo();
        ApplyContractInfo contractInfo = tortoiseApplyData.getApplyContractInfo();
        List<ApplyCarInfo> carInfoList = tortoiseApplyData.getApplyCarInfoList();

        ApplyCarInfo oldCarInfo = null;
        ApplyCarInfo newCarInfo = null;

        // 暂不考虑多车情况
        ApplyCarInfo carInfo = carInfoList.get(0);
        // 挂牌车当做二手车传递至玄武
        if (BusinessTypeEnum.OLD_CAR.getCode().equals(mainInfo.getBusinessType())
            || CarNatureEnum.PLATE_CAR.getCode().equals(mainInfo.getCarNature())) {
            oldCarInfo = carInfo;
        } else if (BusinessTypeEnum.NEW_CAR.getCode().equals(mainInfo.getBusinessType())) {
            newCarInfo = carInfo;
        }
        ApplyAffiliatedInfo affiliatedInfo = tortoiseApplyData.getApplyAffiliatedInfo();
        List<ApplyContactInfo> contactInfoList = tortoiseApplyData.getApplyContactInfoList();
        ApplyDealerInfo dealerInfo = tortoiseApplyData.getApplyDealerInfo();
        List<ApplyDutyPersonInfo> dutyPersonInfoList = tortoiseApplyData.getApplyDutyPersonInfoList();

        ApplyDutyPersonInfo customerInfo = null;
        ApplyDutyPersonInfo sponsorInfo = null;
        ApplyDutyPersonInfo togetherPersonInfo = null;
        if (CollectionUtil.isNotEmpty(dutyPersonInfoList)) {
            for (ApplyDutyPersonInfo applyDutyPersonInfo : dutyPersonInfoList) {
                if (CustRoleEnum.MIANCUST.getCode().equals(applyDutyPersonInfo.getDutyPersonType())) {
                    customerInfo = applyDutyPersonInfo;
                } else if (CustRoleEnum.COMMONCSUT.getCode().equals(applyDutyPersonInfo.getDutyPersonType())) {
                    togetherPersonInfo = applyDutyPersonInfo;
                } else if (CustRoleEnum.GUARANTOR.getCode().equals(applyDutyPersonInfo.getDutyPersonType())) {
                    sponsorInfo = applyDutyPersonInfo;
                }
            }
        }

        GwtMain main = GwtMain.builder()
                .applicationNo(mainInfo.getApplyNo())
                .firstSubmitDate(mainInfo.getFirstSubmitDate())
                .agreeDate(mainInfo.getApproveAgreeDate())
                .rejectReason(mainInfo.getRejectReason())
                .loanAmount(costInfo.getLoanAmount())
                .downPayScale(costInfo.getDownPayScale())
                .loanPeriod(mainInfo.getLoanPeriod())
                .sellName(mainInfo.getSellStaffName())
                .sellPhone(mainInfo.getSellStaffPhone())
                .greenEnergy(mainInfo.getGreenEnergy())
                .dealerName(dealerInfo.getDealerName())
                .direct(dealerInfo.getDirect())
                .online(mainInfo.getOnlineCar())
                .remoteSign(mainInfo.getRemoteSign())
                .oldCar(BusinessTypeEnum.OLD_CAR.getCode().equals(mainInfo.getBusinessType()) ? WhetherEnum.YES.getCode() : WhetherEnum.NO.getCode())
                .affiliated(mainInfo.getAffiliatedMode())
                .businessStatusIn(mainInfo.getBusinessStatusIn())
                .dealerMessage(mainInfo.getDealerSubmitMessage())
                .approveStatus(mainInfo.getApproveStatus())
                .approveStatusName(mainInfo.getApproveStatusName())
                .businessType(mainInfo.getBusinessType())
                .carNature(mainInfo.getCarNature())
                .build();
        List<GwtAppendProduct> appendProductList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(costInfo.getAppendProductInfoList())) {
            for (ApplyAppendProductInfo applyAppendProductInfo : costInfo.getAppendProductInfoList()) {
                appendProductList.add(GwtAppendProduct.builder()
                        .productName(applyAppendProductInfo.getAppendProductName())
                        .amt(applyAppendProductInfo.getAppendProductPrice())
                        .build());
            }
        }

        GwtFinanceProduct financeProduct = GwtFinanceProduct.builder()
                .conditionMark(WhetherEnum.YES.getCode().equals(mainInfo.getConditionMark()) ? "1" : "0")
                .loanAmt(costInfo.getLoanAmount())
                .vendorDiscountAmt(costInfo.getVendorDiscountAmt())
                .vendorDiscountScale(costInfo.getVendorDiscountScale())
                .discountAmt(costInfo.getDiscountAmt())
                .discountScale(costInfo.getDiscountScale())
                .rate(costInfo.getCustomerRate())
                .tailPayScale(costInfo.getTailPayScale())
                .customerRate(costInfo.getCustomerRate())
                .contractAmt(costInfo.getContractAmount())
                .downPayAmt(costInfo.getDownPayAmount())
                .tailPayAmt(costInfo.getTailPayAmount())
                .monthRepay(costInfo.getPeriodRepayAmount())
                .interestAmt(costInfo.getInterestAmount())
                .product(costInfo.getProduct())
                .productName(costInfo.getProductName())
                .repayFrequency(costInfo.getRepayFrequency())
                .appendProducrtList(appendProductList)
                .build();


        GwtContract contract = GwtContract.builder()
                .ticketUnitName(contractInfo.getTicketUnitName())
                .contactStatus(contractInfo.getContractInnerStatus())
                .contactStatusName(contractInfo.getContractInnerStatusName())
                .engineNo(Objects.nonNull(oldCarInfo)
                        ? oldCarInfo.getEngineNo() : newCarInfo.getEngineNo())
                .vin(Objects.nonNull(oldCarInfo)
                        ? oldCarInfo.getVin() : newCarInfo.getVin())
                .build();

        GwtOldCar oldCar = null;

        if (Objects.nonNull(oldCarInfo)) {
            oldCar = GwtOldCar.builder()
                    .newCarSalePrice(oldCarInfo.getNewCarSalePrice())
                    .saleName(oldCarInfo.getCarVendorName())
                    .salePhone(oldCarInfo.getCarVendorPhone())
                    .saleAddress(oldCarInfo.getCarVendorAddress())
                    .plateNo(oldCarInfo.getLicensePlate())
                    .sellPrice(CarNatureEnum.PLATE_CAR.getCode().equals(mainInfo.getCarNature())
                            ? costInfo.getCarPrice()
                            : oldCarInfo.getSecondDealCarPrice())
                    .assessPrice(oldCarInfo.getThirdProspectPrice())
                    .firstRegisterDate(oldCarInfo.getFirstRegisterDate())
                    .carBodyLevel(oldCarInfo.getCarModel())
                    .brand(oldCarInfo.getBrand())
                    .brandName(oldCarInfo.getBrandName())
                    .carStyle(oldCarInfo.getCarStyle())
                    .carStyleName(oldCarInfo.getCarStyleName())
                    .carType(oldCarInfo.getVehicleType())
                    .carModel(oldCarInfo.getVehicleModel())
                    .carModelName(oldCarInfo.getVehicleModelName())
                    .vin(oldCarInfo.getVin())
                    .engineNo(oldCarInfo.getEngineNo())
                    .registerProvince(oldCarInfo.getRegisterProvince())
                    .registerProvinceName(oldCarInfo.getRegisterProvinceName())
                    .registerCity(oldCarInfo.getRegisterCity())
                    .registerCityName(oldCarInfo.getRegisterCityName())
                    .buyProvince(oldCarInfo.getBuyProvince())
                    .buyProvinceName(oldCarInfo.getBuyProvinceName())
                    .buyCity(oldCarInfo.getBuyCity())
                    .buyCityName(oldCarInfo.getBuyCityName())
                    .plateProvince(oldCarInfo.getPlateProvince())
                    .plateProvinceName(oldCarInfo.getPlateProvinceName())
                    .plateCity(oldCarInfo.getPlateCity())
                    .plateCityName(oldCarInfo.getPlateCityName())
                    .buyPurpose(oldCarInfo.getBuyPurpose())
                    .ownerIdCard(oldCarInfo.getOwnerIdCard())
                    .ownerCompanyName(oldCarInfo.getOwnerCompanyName())
                    .hasPlate(oldCarInfo.getRegistration())
                    .bornDate(oldCarInfo.getMakeDate())
                    .ticketDate(oldCarInfo.getPlateCarTicketDate())
                    .transferTime(oldCarInfo.getTransferTimes())
                    .mileage(oldCarInfo.getMileage())
                    .build();
        }

        GwtNewCar newCar = null;
        if (Objects.nonNull(newCarInfo)) {
            newCar = GwtNewCar.builder()
                    .assetCode(newCarInfo.getAssetCode())
                    .optionPrice(newCarInfo.getOptionPrice())
                    .guidePrice(newCarInfo.getGuidePrice())
                    .brand(newCarInfo.getBrand())
                    .brandName(newCarInfo.getBrandName())
                    .vehicleType(newCarInfo.getVehicleType())
                    .vehicleModel(newCarInfo.getVehicleModel())
                    .vehicleModelName(newCarInfo.getVehicleModelName())
                    .newCarStyle(newCarInfo.getCarStyle())
                    .newCarStyleName(newCarInfo.getCarStyleName())
                    .buyPurpose(newCarInfo.getBuyPurpose())
                    .buyProvince(newCarInfo.getBuyProvince())
                    .buyProvinceName(newCarInfo.getBuyProvinceName())
                    .buyCity(newCarInfo.getBuyCity())
                    .buyCityName(newCarInfo.getBuyCityName())
                    .plateProvince(newCarInfo.getPlateProvince())
                    .plateProvinceName(newCarInfo.getPlateProvinceName())
                    .plateCity(newCarInfo.getPlateCity())
                    .plateCityName(newCarInfo.getPlateCityName())
                    .sellPrice(newCarInfo.getNewCarSalePrice())
                    .build();
        }
        List<GwtContact> contactList = new ArrayList<>();
        for (ApplyContactInfo contactInfo : contactInfoList) {
            contactList.add(GwtContact.builder()
                    .userCode(contactInfo.getUserCode())
                    .idCard(contactInfo.getIdCard())
                    .companyName(contactInfo.getCompanyName())
                    .companyPhone(contactInfo.getCompanyPhone())
                    .liveAddress(contactInfo.getLiveAddress())
                    .monthIncome(contactInfo.getMonthIncome())
                    .name(contactInfo.getName())
                    .phone(contactInfo.getPhone())
                    .relation(contactInfo.getRelationShip())
                    .build());

        }

        GwtAffiliated affiliated = GwtAffiliated.builder()
                .legalPersonPhone(affiliatedInfo.getLegalPersonPhone())
                .legalPersonName(affiliatedInfo.getLegalPersonName())
                .enable(affiliatedInfo.getStatus())
                .registerDate(affiliatedInfo.getRegisterDate())
                .companyPhone(affiliatedInfo.getCompanyPhone())
                .affiliatedMode(affiliatedInfo.getAffiliatedMode())
                .companyName(affiliatedInfo.getCompanyName())
                .companyProvince(affiliatedInfo.getCompanyProvince())
                .companyProvinceName(affiliatedInfo.getCompanyProvinceName())
                .companyCity(affiliatedInfo.getCompanyCity())
                .companyCityName(affiliatedInfo.getCompanyCityName())
                .build();

        GwtDealer dealer = GwtDealer.builder()
                .name(dealerInfo.getDealerName())
                .dealerProvince(dealerInfo.getProvince())
                .dealerProvinceName(dealerInfo.getProvinceName())
                .dealerCity(dealerInfo.getCity())
                .dealerCityName(dealerInfo.getCityName())
                .registerDate(dealerInfo.getStartWorkDate())
                .unifiedSocialCreditCode(dealerInfo.getUnifiedSocialCreditCode())
                .dealerLevel(dealerInfo.getDealerLevel())
                .dealerBelong(dealerInfo.getChannelBelong())
                .build();


        GwtCustomer customer = getDutyInfo(customerInfo);

        GwtCustomer togetherPerson = getDutyInfo(togetherPersonInfo);

        GwtCustomer sponsor = getDutyInfo(sponsorInfo);
        GwtApplyBean response = GwtApplyBean.builder()
                .apply(GwtApply.builder()
                        .main(main)
                        .financeProduct(financeProduct)
                        .contract(contract)
                        .oldCar(oldCar)
                        .newCar(newCar)
                        .contactList(contactList)
                        .affiliated(affiliated)
                        .dealer(dealer)
                        .build())
                .applicationNo(tortoiseApplyData.getApplyNo())
                .caMainId(tortoiseApplyData.getMainId())
                .sysCallbackId(tortoiseApplyData.getSerialNumber())
                .customer(customer)
                .togetherPerson(togetherPerson)
                .sponsor(sponsor)
                .build();

        return GwtTortoiseResponse.successData(RefDataUtil.addRefData(response));
    }

    /**
     * Author Peng Jinbo
     * Get duty info gwt customer
     *
     * @param customerInfo customer info
     * @return the gwt customer
     */
    private GwtCustomer getDutyInfo(ApplyDutyPersonInfo customerInfo) {
        if (Objects.isNull(customerInfo)) {
            return null;
        }
        List<GwtAddress> customerAddress = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(customerInfo.getDutyPersonAddressInfos())) {
            for (ApplyDutyPersonAddressInfo address : customerInfo.getDutyPersonAddressInfos()) {
                customerAddress.add(GwtAddress.builder()
                        .addressProvince(address.getAddressProvince())
                        .addressProvinceName(address.getAddressProvinceName())
                        .addressCity(address.getAddressCity())
                        .addressCityName(address.getAddressCityName())
                        .addressDetail(address.getAddressDetail())
                        .addressType(address.getAddressType())
                        .houseType(address.getHouseType())
                        .postCode(address.getPostCode())
                        .startLiveDate(address.getCurrentAddressLiveDate())
                        .build());
            }
        }

        GwtDutyDetail dutyDetail = GwtDutyDetail.builder()
                .userCode(customerInfo.getUserCode())
                .name(customerInfo.getName())
                .cardType(customerInfo.getCardType())
                .idCard(customerInfo.getIdCard())
                .cardEndDate(customerInfo.getIdCardEndDate())
                .birthday(customerInfo.getBirthday())
                .sex(customerInfo.getSex())
                .marryStatus(customerInfo.getMarryStatus())
                .education(customerInfo.getEducation())
                .phone(customerInfo.getPhone())
                .ageYear(customerInfo.getAgeOfYear())
                .ageMonth(customerInfo.getAgeOfMonth())
                .outsidePhone(customerInfo.getOutsidePhone())
                .income(customerInfo.getSelfMonthIncome())
                .familyIncome(customerInfo.getFamilyMonthIncome())
                .familySpend(customerInfo.getFamilyMonthUsed())
                .monthRepay(customerInfo.getMonthRepay())
                .unRepayLoanAmt(customerInfo.getUnRepayAmount())
                .companyName(customerInfo.getCompanyName())
                .industryType(customerInfo.getIndustryType())
                .jobType(customerInfo.getJobType())
                .jobPosition(customerInfo.getJobPosition())
                .workingLimit(customerInfo.getWorkingLimit())
                .companyPhone(customerInfo.getCompanyPhone())
                .driverLicence(customerInfo.getDriverLicense())
                .driverNo(customerInfo.getRecordNo())
                .relationship(customerInfo.getRelationship())
                .addressList(customerAddress).build();
        return GwtCustomer.builder().gwtDutyDetail(dutyDetail).build();
    }

    /**
     * Author Peng Jinbo
     * Notice gwt tortoise response
     *
     * @param notice notice
     * @return the gwt tortoise response
     */
    @Override
    public GwtTortoiseResponse notice(GwtTortoiseReq notice) {
        afsCreditTortoiseRecordService.noticeToClient(notice, GwtTortoiseNoticeClientUri.NOTICE_CLIENT_URI_APPLY);
        return GwtTortoiseResponse.success();
    }

}
